from .proto.serializers import *
from apps.devices.serializers import ControllersSerializer
from apps.devices.models import Sensor
import struct


class readConfigPackagerItem(Serializer):
    item = IntegerField(length=1, order=1, doc='配置类空间')


class unpackRegisterMessage(Serializer):
    hardware_model = StringField(length=17, order=1, doc='硬件型号')
    manufacture_tmie = StringField(length=9, order=2, doc='出厂日期')
    hardware_version = StringField(length=9, order=3, doc='硬件版本')
    software_version = StringField(length=9, order=4, doc='软件版本')
    device_serial_number = StringField(length=33, order=5, doc='序列号')
    status = IntegerField(length=1, order=5, doc='状态')
    setting = IntegerField(length=1, order=6, doc='主从配置')
    mode = IntegerField(length=1, order=7, doc='设备模式')


class SensorMessage(Serializer):
    start = IntegerField(
        length=1,
        order=1,
        doc='有效标志'
    )
    input_number = IntegerField(
        length=1,
        order=2,
        doc='输入1~N编号'
    )
    name = StringField(
        length=17,
        order=3,
        doc='输入1~N名称'
    )
    measuring = IntegerField(
        length=1,
        order=4,
        doc='输入1~N测量种类'
    )
    status = IntegerField(
        length=1,
        order=5,
        doc='输入1~N是否启用'
    )
    led_status = IntegerField(
        length=1,
        order=6,
        doc='输入1~N是否LED启用'
    )
    addr_485 = IntegerField(
        bytesorder='little',
        length=4,
        order=7,
        doc='输入1~N485地址'
    )
    end_type = IntegerField(
        length=1,
        order=8,
        doc='大小端'
    )
    data_format = IntegerField(
        length=1,
        order=9,
        doc='输入1~N数据类型'
    )
    register_start = IntegerField(
        bytesorder='little',
        length=2,
        order=10,
        doc='输入1~N寄存器起始地址'
    )
    register_length = IntegerField(
        length=1,
        order=11, doc='输入1~N寄存器长度')
    ratio_a = FloatField(
        length=4,
        bytesorder='little',
        order=12,
        doc='输入1~N系数A，'
    )
    ratio_b = FloatField(
        length=4,
        bytesorder='little',
        order=13,
        doc='输入1~N系数b'
    )


class SerialNumberSerializer(Serializer):
    item = IntegerField(
        length=1,
        order=1,
        default=11,
        doc='读取的config类'
    )
    offset = IntegerField(
        length=1,
        order=2,
        doc='偏移'
    )
    read = IntegerField(
        length=1,
        order=2,
        doc='读取字节数'
    )


class HeartbeatSerializer(Serializer):
    status = IntegerField(
        length=1,
        order=1,
        default=11,
        doc='返回状态'
    )
    result = IntegerField(
        length=1,
        order=2,
        doc='返回结果'
    )
    date = StringField(
        length=6,
        order=3,
        doc='返回结果'
    )
    time = StringField(
        length=6,
        order=4,
        doc='返回结果'
    )


class RegisterMessageSerializer(Serializer):
    status = IntegerField(
        length=2,
        order=1,
        doc='返回状态'
    )


class ReadConfigSerializer(Serializer):
    item = IntegerField(
        length=1,
        order=1,
        doc='配置类空间'
    )
    offset = IntegerField(
        length=2,
        order=2,
        doc='偏移'
    )
    length = IntegerField(
        length=2,
        order=3,
        doc='读长度'
    )


class WriteConfigSerializer(Serializer):
    item = IntegerField(
        length=1,
        order=1,
        doc='配置类空间'
    )
    offset = IntegerField(
        length=2,
        order=2,
        doc='偏移',

    )
    length = IntegerField(
        length=2,
        order=3,
        doc='写长度'
    )
    data = Field(
        length=0,
        order=4,
        doc='数据'
    )


class SettingSerializer(Serializer):
    ip = Field(
        length=33,
        order=1,
        doc='域名或者IP'
    )
    port = IntegerField(
        length=2,
        order=1,
        doc='端口'
    )


class SensorDataResPackager(Serializer):
    code = IntegerField(
        length=1,
        order=1,
        doc='操作码'
    )
    result = IntegerField(
        length=1,
        order=1,
        doc='结果'
    )


class SensorDataReqPackager(Serializer):
    time_ticket = IntegerField(
        length=4,
        bytesorder='little',
        order=1,
        doc='事件ticket'
    )
    input_type = IntegerField(
        length=1,
        order=2,
        doc='输入种类'
    )
    input_channel = IntegerField(
        length=1,
        order=3,
        doc='输入路号'
    )
    collection = IntegerField(
        length=1,
        order=4,
        doc='输入种类'
    )
    data_format = IntegerField(
        length=1,
        order=5,
        doc='数据格式'
    )
    data = Field(
        length=4,
        order=6,
        doc='data'
    )


class AutoRuleSerializer(Serializer):
    rule_code = IntegerField(
        order=0,
        length=1,
        doc='开始标志'
    )
    rule_number = IntegerField(
        order=1,
        length=1,
        doc='编号'
    )
    status = IntegerField(
        order=2,
        length=1,
        doc='规则1~N是否启用'
    )
    time_status = IntegerField(
        order=3,
        length=1,
        doc='时间段是否开启'
    )
    time_start = StringField(
        order=4,
        length=6,
        doc='规则1~N时间段开始点'
    )
    time_end = StringField(
        order=5,
        length=6,
        doc='规则1~N时间段结束点'
    )
    rule_status_1 = IntegerField(
        order=6,
        length=1,
        doc='条件1_启用'
    )
    rule_close_value_1 = IntegerField(
        order=7,
        length=1,
        doc='条件1_不启用时逻辑值'
    )
    rule_input_type_1 = IntegerField(
        order=8,
        length=1,
        doc='条件1_输入种类'
    )
    rule_input_channel_1 = IntegerField(
        order=9,
        length=1,
        doc='条件1_输入路号'
    )
    rule_input_collection_1 = IntegerField(
        order=10,
        length=1,
        doc='条件1_输入采集量'
    )
    
    rule_compare_1 = IntegerField(
        order=11,
        length=1,
        doc='条件1_比较'
    )
    rule_threshold_1 = FloatField(
        order=12,
        bytesorder='little',
        length=4,
        doc='条件1_门限值'
    )
    rule_float_1 = FloatField(
        order=13,
        bytesorder='little',
        length=4,
        doc='条件1_浮动值'
    )
    rule_operation = IntegerField(
        order=14,
        length=1,
        doc='条件运算'
    )
    rule_status_2 = IntegerField(
        order=15,
        length=1,
        doc='条件2_启用'
    )
    rule_close_value_2 = IntegerField(
        order=16,
        length=1,
        doc='条件2_不启用时逻辑值'
    )
    rule_input_type_2 = IntegerField(
        order=17,
        length=1,
        doc='条件2_输入种类'
    )
    rule_input_channel_2 = IntegerField(
        order=18,
        length=1,
        doc='条件2_输入路号'
    )
    rule_input_collection_2 = IntegerField(
        order=19,
        length=1,
        doc='条件2_输入采集量'
    )
    rule_compare_2 = IntegerField(
        order=20,
        length=1,
        doc='条件2_比较'
    )
    rule_threshold_2 = FloatField(
        bytesorder='little',
        order=21,
        length=4,
        doc='条件2_门限值'
    )
    rule_float_2 = FloatField(
        order=22,
        bytesorder='little',
        length=4,
        doc='条件2_浮动值'
    )
    output_type = IntegerField(
        order=23,
        length=1,
        doc='规则1~N输出类型'
    )
    output_channle = IntegerField(
        order=24,
        length=1,
        doc='规则1~N输出路号'
    )
    output_value = IntegerField(
        order=25,
        bytesorder='little',
        length=4,
        doc='规则1~N输出值'
    )

    @classmethod
    def transform_rule_threshold_1(cls, data, items, dev):

        return cls._get_format(items['rule_input_channel_1'], data, dev)

    @classmethod
    def transform_rule_float_1(cls, data, items, dev):
        return cls._get_format(items['rule_input_channel_1'], data, dev)

    @classmethod
    def transform_rule_threshold_2(cls, data, items, dev):
        return cls._get_format(items['rule_input_channel_2'], data, dev)

    @classmethod
    def transform_rule_float_2(cls, data, items, dev):
        return cls._get_format(items['rule_input_channel_2'], data, dev)

    @classmethod
    def _get_format(self, channle, data, dev):
        try:
            sensor = Sensor.objects.filter(
                input_number=channle, devices_id=dev.id).first()
            parse_str = [
                ['<i', '<I', '<H', '<f', '<?'],
                ['>i', '>I', '>H', '>f', '>?'],
            ]
            types = [
                [int, int, int, float, bytes],
                [int, int, int, float, bytes]
            ]
            parse_type = types[sensor.end_type][sensor.data_format]
            format_str = parse_str[sensor.end_type][sensor.data_format]
            print(format_str, parse_type)
        except Exception as e:
            res = b'\x00\x00\x00\x00'
        else:
            res = struct.pack(format_str, parse_type(data))

        return res


class ReadAutoRuleSerializer(Serializer):
    code = IntegerField(
        length=1,
        order=1,
        doc='类型  0 全部定时规则  1  1号定时规则'
    )


class HardwareSerializer(Serializer):
    number_input_channle = IntegerField(
        length=1,
        order=1,
        doc='数字量输入路数'
    )
    mock_input_channle = IntegerField(
        length=1,
        order=1,
        doc='模拟量输入路数'
    )
    number_output_channle = IntegerField(
        length=1,
        order=1,
        doc='数字量输出路数'
    )
    mock_output_channle = IntegerField(
        length=1,
        order=1,
        doc='模拟量输出路数'
    )
    channle_485 = IntegerField(
        length=1,
        order=1,
        doc='485路数'
    )


class LocalNetWorkSerializer(Serializer):
    ip_mode = IntegerField(
        length=1,
        order=1,
        doc='网络模式'
    )
    ip_addr = StringField(
        length=4,
        order=2,
        doc='网络模式'
    )
    mac = StringField(
        length=7,
        order=3,
        doc='网络模式'
    )
    sub_network = StringField(
        length=1,
        order=4,
        doc='网络模式'
    )
    gateway = StringField(
        length=1,
        order=5,
        doc='网络模式'
    )
    dns1 = StringField(
        length=1,
        order=6,
        doc='网络模式'
    )
    dns2 = StringField(
        length=1,
        order=7,
        doc='网络模式'
    )


class RemoteNetworkSerializer(Serializer):
    token = StringField(
        length=33,
        order=1,
        doc='网络模式'
    )
    heartbeat_interval = IntegerField(
        bytesorder='little',
        length=2,
        order=2,
        doc='心跳间隔'
    )
    heartbeat_timeout = IntegerField(
        bytesorder='little',
        length=2,
        order=3,
        doc='超时时间'
    )
    auto_upload = IntegerField(
        bytesorder='little',
        length=1,
        order=4,
        doc='自动上传数据使能'
    )
    upload_interval = IntegerField(
        bytesorder='little',
        length=2,
        order=5,
        doc='上传数据间隔'
    )
    apn = IntegerField(
        bytesorder='little',
        length=9,
        order=6,
        doc='apn'
    )
    apn_user = IntegerField(
        bytesorder='little',
        length=17,
        order=7,
        doc='用户'
    )
    apn_password = IntegerField(
        bytesorder='little',
        length=17,
        order=8,
        doc='密码'
    )

    class remote_ips(Serializer):
        order = 9
        start = IntegerField(
            bytesorder='little',
            length=1,
            order=1,
            doc='有效标志'
        )
        code = IntegerField(
            bytesorder='little',
            length=1,
            order=2,
            doc='服务器编号'
        )
        status = IntegerField(
            bytesorder='little',
            length=1,
            order=3,
            doc='是否启用'
        )
        addr = StringField(
            length=33,
            bytesorder='little',
            order=4,
            doc='IP'
        )
        port = IntegerField(
            bytesorder='little',
            length=2,
            order=5,
            doc='port'
        )


class CacheSerializer(Serializer):
    is_upload = IntegerField(
        length=1,
        order=1,
        doc='是否上报'
    )
    time_stamp = IntegerField(
        bytesorder='little',
        length=2,
        order=2,
        doc='时间戳'
    )
    input_type = IntegerField(
        length=1,
        order=3,
        doc='输入种类'
    )
    input_channle = IntegerField(
        length=1,
        order=4,
        doc='输入路号'
    )
    data = IntegerField(
        bytesorder='little',
        length=4,
        order=5,
        doc='数据'
    )


class StorageSerializer(Serializer):
    is_use = IntegerField(
        length=1,
        order=1,
        doc='存储功能是否启用'
    )
    mode = IntegerField(
        length=1,
        order=2,
        doc='存储模式  0循环  1提示'
    )
    save_interval = IntegerField(
        length=2,
        bytesorder='little',
        order=3,
        doc='存储间隔'
    )
    save_limit = IntegerField(
        length=2,
        bytesorder='little', order=4, doc='存储最大数量')
    last_write = IntegerField(
        bytesorder='little',
        length=4,
        order=5,
        doc='上次写位置'
    )
    last_read = IntegerField(
        bytesorder='little',
        length=4,
        order=5,
        doc='上次读位置'
    )


class Setting_485(Serializer):
    start = IntegerField(
        length=1,
        order=1,
        doc='有效标志'
    )

    class settings(Serializer):
        order = 2
        start = IntegerField(
            length=1,
            order=1,
            doc='有效标志'
        )
        line_number = IntegerField(
            length=1,
            order=2,
            doc='485总线号'
        )
        br_number = IntegerField(
            length=1,
            order=3,
            doc='波特率'
        )
        check = IntegerField(
            length=1,
            order=4,
            doc='校验位'
        )
        copy_to_gprs = IntegerField(
            length=1,
            order=5,
            doc='上行数据是否复制给GPRS'
        )


class NumberInputSetting(Serializer):
    start = IntegerField(
        length=1,
        order=1,
        doc='有效标志'
    )

    class settings(Serializer):
        order = 2
        start = IntegerField(
            length=1,
            order=0,
            doc='有效标志'
        )
        number = IntegerField(
            length=1,
            order=1,
            doc='输入1~N编号'
        )
        name = StringField(
            length=10,
            order=2,
            doc='输入1~N名称'
        )
        measuring = IntegerField(
            length=1,
            order=3,
            doc='输入1~N测量种类'
        )
        is_use = IntegerField(
            length=1,
            order=4,
            doc='输入1~N是否启用'
        )
        led_is_use = IntegerField(
            length=1,
            order=5,
            doc='输入1~N是否LED启用'
        )
        get_value_setting = IntegerField(
            length=1,
            order=6,
            doc='取值配置'
        )


class MockInputSetting(Serializer):
    start = IntegerField(
        length=1,
        order=1,
        doc='有效标志'
    )

    class settings(Serializer):
        order = 2
        start = IntegerField(
            length=1,
            order=0,
            doc='有效标志'
        )
        number = IntegerField(
            length=1,
            order=1,
            doc='输入1~N编号'
        )
        name = StringField(
            length=17,
            order=2,
            doc='输入1~N名称'
        )
        measuring = IntegerField(
            length=1,
            order=3,
            doc='输入1~N测量种类'
        )
        is_use = IntegerField(
            length=1,
            order=4,
            doc='输入1~N是否启用'
        )
        led_is_use = IntegerField(
            length=1,
            order=5,
            doc='输入1~N是否LED启用'
        )
        value_type = IntegerField(
            length=1,
            order=6,
            doc='模拟量类型  0：模拟量4~20mA   1：0~5V    2，0~10V'
        )
        input_serial_number_a = FloatField(
            length=4,
            bytesorder='little',
            order=7,
            doc='输入1~N系数A，'
        )
        input_serial_number_b = FloatField(
            length=4,
            bytesorder='little',
            order=8,
            doc='输入1~N系数b'
        )


class SensorInputSerializer(Serializer):
    settings = SensorMessage


class NumberOutPutSerializer(Serializer):
    start = IntegerField(
        length=1,
        order=1,
        doc='有效标志'
    )
    settings = ControllersSerializer


class NumberGroupOutPutSerializer(Serializer):
    start = IntegerField(
        length=1,
        order=1,
        doc='有效标志'
    )

    class settings(Serializer):
        order = 2
        start = IntegerField(
            length=1,
            order=0,
            doc='有效标志'
        )
        number = IntegerField(
            length=1,
            bytesorder='little',
            order=1,
            doc='编号'
        )
        is_use = IntegerField(
            length=1,
            order=2,
            doc='是否启用'
        )
        mode = IntegerField(
            length=1,
            order=3,
            doc='控制模式 0：手动 1：定时 2：自动'
        )
        group_mode = IntegerField(
            length=1,
            order=4,
            doc='0：单机控制 1: 组合控制'
        )
        sub_device_1 = IntegerField(
            length=1,
            order=5,
            doc='子1设备号'
        )
        sub_device_2 = IntegerField(
            length=1,
            order=6,
            doc='子2设备号'
        )
        default_value = IntegerField(
            bytesorder='little',
            length=4,
            order=7,
            doc='初始默认值'
        )


class MockOutPutSerializer(Serializer):
    start = IntegerField(
        length=1,
        order=1,
        doc='有效标志'
    )

    class settings(Serializer):
        order = 2
        start = IntegerField(
            length=1,
            order=0,
            doc='有效标志'
        )
        number = IntegerField(
            length=1,
            bytesorder='little',
            order=1,
            doc='编号'
        )
        is_use = IntegerField(
            length=1,
            order=2,
            doc='是否启用'
        )
        mode = IntegerField(
            length=1,
            order=3,
            doc='控制模式 0：手动 1：定时 2：自动'
        )
        default_value = FloatField(
            bytesorder='little',
            length=4,
            order=4,
            doc='初始默认值'
        )


class AutoUploadSerializer(Serializer):
    status = IntegerField(
        bytesorder='little',
        length=1,
        order=1,
        doc='状态'
    )


class ReadControlStatusSerializer(Serializer):
    output_type = IntegerField(
        bytesorder='little',
        order=1,
        length=1,
        doc='数字输出种类'
    )
    output_channle = IntegerField(
        bytesorder='little',
        order=2,
        length=1,
        doc='输出路号'
    )


class ControlStatusSerializer(Serializer):
    code = IntegerField(
        bytesorder='little',
        order=1,
        length=1,
        doc='数字输出种类'
    )
    result = IntegerField(
        bytesorder='little',
        order=2,
        length=1,
        doc='数字输出种类'
    )

    class controlls(Serializer):
        order = 3
        time_ticket = IntegerField(
            length=4,
            order=1,
            doc='事件ticket'
        )
        output_type = IntegerField(
            bytesorder='little',
            order=2,
            length=1,
            doc='数字输出种类'
        )
        output_channle = IntegerField(
            bytesorder='little',
            order=3,
            length=1,
            doc='输出路号'
        )
        data_simple_format = IntegerField(
            bytesorder='little',
            order=4,
            length=1,
            doc='数据类型'
        )
        data_format = IntegerField(
            bytesorder='little',
            order=5,
            length=1,
            doc='数据类型'
        )
        data = IntegerField(
            bytesorder='little',
            order=6,
            length=4,
            doc='输出数据'
        )


class WriteControlStatusSerializer(Serializer):
    output_type = IntegerField(
        bytesorder='little',
        order=0,
        length=1,
        doc='数字输出种类'
    )
    number = IntegerField(
        bytesorder='little',
        order=1,
        length=1,
        doc='输出路号'
    )
    data = IntegerField(
        order=2,
        length=4,
        doc='输出路号'
    )


class TransmissionSerializer(Serializer):
    line_number = IntegerField(
        length=1,
        order=1,
        doc='总线号'
    )
    data_length = IntegerField(
        length=2,
        order=2,
        doc='数据长度'
    )
    data = Field(
        order=3,
        doc='数据长度'
    )


class AutoRuleAction(Serializer):
    action = IntegerField(
        length=1,
        order=1,
        doc='操作'
    )
    data = Field(
        order=1,
        doc='操作'
    )
